package liveData.migration.toPhoenix.util;

import liveData.migration.toPhoenix.exception.SQLWriterErrorCode;
import liveData.migration.toPhoenix.exception.SqlParseException;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.Types;
import java.util.LinkedHashMap;
import java.util.regex.Pattern;

/**
 * @program: LiveDataMigrationToPhoenix
 * @description:
 * @author: sunteng
 * @create: 2020-04-29 14:03
 **/
@Slf4j
public class SqlHelper {
    private ParseHelper parseHelper = new ParseHelper();

    public void setupStatement(LinkedHashMap<String, Integer> columnsTypes, PreparedStatement ps) {

        final int[] pos = {1};
        columnsTypes.forEach((k, v) -> {
            try {
                if (k.contains(",")) {
                    k = k.split(",")[0];
                }
                setupColumn(pos[0], v, k, ps);
            } catch (Exception e) {
                log.error("setupStatement error [{}]", e.getMessage());
            }
            pos[0]++;
        });
    }

    private void setupColumn(int pos, int sqlType, String col, PreparedStatement ps) throws Exception {
        System.out.println("col ,sqlType :" + col + "," + sqlType);
        if (StringUtils.isNotEmpty(col)) {
            switch (sqlType) {
                case Types.CHAR:
                case Types.VARCHAR:
                    ps.setString(pos, col);
                    break;

                case Types.BINARY:
                case Types.VARBINARY:
                    ps.setBytes(pos, col.getBytes("UTF-8"));
                    break;

                case Types.BOOLEAN:
                    ps.setBoolean(pos, Boolean.valueOf(col));
                    break;

                case Types.TINYINT:
                case ConstantUtil.TYPE_UNSIGNED_TINYINT:
                    ps.setByte(pos, Long.valueOf(col).byteValue());
                    break;

                case Types.SMALLINT:
                case ConstantUtil.TYPE_UNSIGNED_SMALLINT:
                    ps.setShort(pos, Long.valueOf(col).shortValue());
                    break;

                case Types.INTEGER:
                case ConstantUtil.TYPE_UNSIGNED_INTEGER:
                    ps.setInt(pos, Long.valueOf(col).intValue());
                    break;

                case Types.BIGINT:
                case ConstantUtil.TYPE_UNSIGNED_LONG:
                    if (Pattern.matches(ConstantUtil.REGEX_TIME, col)) {
                        ps.setLong(pos, parseHelper.parseVarchar(col).longValue());
                    } else {
                        ps.setLong(pos, Long.valueOf(col));
                    }
                    break;

                case Types.FLOAT:
                    ps.setFloat(pos, Double.valueOf(col).floatValue());
                    break;

                case Types.DOUBLE:
                    ps.setDouble(pos, Double.valueOf(col));
                    break;

                case Types.DECIMAL:
                    ps.setBigDecimal(pos, new BigDecimal(col));
                    break;

                case Types.DATE:
                case ConstantUtil.TYPE_UNSIGNED_DATE:
                    ps.setDate(pos, new java.sql.Date(parseHelper.parseVarchar(col).longValue()));
                    break;

                case Types.TIME:
                case ConstantUtil.TYPE_UNSIGNED_TIME:
                    ps.setTime(pos, new java.sql.Time(parseHelper.parseVarchar(col).longValue()));
                    break;

                case Types.TIMESTAMP:
                case ConstantUtil.TYPE_UNSIGNED_TIMESTAMP:
                    ps.setTimestamp(pos, new java.sql.Timestamp(parseHelper.parseVarchar(col).longValue()));
                    break;

                default:
                    throw new SqlParseException(SQLWriterErrorCode.ILLEGAL_VALUE,
                            "不支持您配置的列类型:" + sqlType + "");

            } // end switch
        } else {

            ps.setObject(pos, getEmptyValue(sqlType));

        }
    }


    /**
     * 根据类型获取"空值"
     * 值类型的空值都是0，bool是false，String是空字符串
     *
     * @param sqlType sql数据类型，定义于{@link Types}
     */
    private Object getEmptyValue(int sqlType) {
        switch (sqlType) {
            case Types.VARCHAR:
                return "";

            case Types.BOOLEAN:
                return false;

            case Types.TINYINT:
            case ConstantUtil.TYPE_UNSIGNED_TINYINT:
                return (byte) 0;

            case Types.SMALLINT:
            case ConstantUtil.TYPE_UNSIGNED_SMALLINT:
                return (short) 0;

            case Types.INTEGER:
            case ConstantUtil.TYPE_UNSIGNED_INTEGER:
                return (int) 0;

            case Types.BIGINT:
            case ConstantUtil.TYPE_UNSIGNED_LONG:
                return (long) 0;

            case Types.FLOAT:
                return (float) 0.0;

            case Types.DOUBLE:
                return (double) 0.0;

            case Types.DECIMAL:
                return new BigDecimal(0);

            case Types.DATE:
            case ConstantUtil.TYPE_UNSIGNED_DATE:
                return new java.sql.Date(0);

            case Types.TIME:
            case ConstantUtil.TYPE_UNSIGNED_TIME:
                return new java.sql.Time(0);

            case Types.TIMESTAMP:
            case ConstantUtil.TYPE_UNSIGNED_TIMESTAMP:
                return new java.sql.Timestamp(0);

            case Types.BINARY:
            case Types.VARBINARY:
                return new byte[0];

            default:
                throw new SqlParseException(SQLWriterErrorCode.ILLEGAL_VALUE,
                        "不支持您配置的列类型:" + sqlType + "");
        }
    }
}
